package com.societyGames.flashForms
{
	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Rectangle;

	public class ScrollContainer extends SingleChildContainer
	{
		private var _horizontalTrack:Sprite;
		private var _horizontalThumb:Sprite;
		private var _horizontalDraggable:Draggable;
		private var _verticalTrack:Sprite;
		private var _verticalThumb:Sprite;
		private var _verticalDraggable:Draggable;
		private var _desiredWidth:Number;
		private var _desiredHeight:Number;
		private var _visibleRectangle:Rectangle = new Rectangle();
		private var _horizontalVisible:Boolean;
		private var _verticalVisible:Boolean;
		private var _availableWidth:Number;
		private var _availableHeight:Number;
		private var _scrollRectSprite:Sprite = new Sprite(); //A special sprite for applying the scroll rect.
		private var _horizontalPercent:Number; //What percent to the right are we showing?
		private var _verticalPercent:Number;  //What percent to the left are we showing?

		public function ScrollContainer(horizontalTrack:Sprite, horizontalThumb:Sprite, verticalTrack:Sprite, verticalThumb:Sprite)
		{
			this._horizontalTrack = horizontalTrack;
			this._horizontalThumb = horizontalThumb;
			this._horizontalDraggable = new Draggable(this._horizontalThumb, new Rectangle());
			this._horizontalDraggable.movedEventObject.addEventListener(horizontalMovedHandler);
			this._horizontalDraggable.droppedEventObject.addEventListener(horizontalDroppedHandler);
			
			this._verticalTrack = verticalTrack;
			this._verticalThumb = verticalThumb;
			this._verticalDraggable = new Draggable(this._verticalThumb, new Rectangle());
			this._verticalDraggable.movedEventObject.addEventListener(verticalMovedHandler);
			this._verticalDraggable.droppedEventObject.addEventListener(verticalDroppedHandler);
		
			this.addChild(this._scrollRectSprite);
			this.addChild(this._horizontalTrack);
			this.addChild(this._verticalTrack);
			this.addChild(this._horizontalThumb);
			this.addChild(this._verticalThumb);
			zeroThumbPositions();
		}
		
		public override function set width(value:Number):void
		{
			if (value != this._desiredWidth)
			{
				this._desiredWidth = value;
				calculateProportions();
			}
		}
		
		public override function set height(value:Number):void
		{	
			if (value != this._desiredHeight)
			{
				this._desiredHeight = value;
				calculateProportions();
			}
		}

		public override function set child(value:DisplayObject):void
		{
			if (this._child != value)
			{
				var changeSize:IChangeSize;
				//Remove the old one.
				if (this._child != null)
				{
					changeSize = this._child as IChangeSize;
					if (changeSize != null)
					{
						changeSize.sizeChangedEventObject.removeEventListener(childSizeChangedHandler);
					}
					this._scrollRectSprite.removeChild(this._child);
				}
				this._child = value;
				//Deal with the new one.
				if (this._child != null)
				{	
					changeSize = this._child as IChangeSize;
					if (changeSize != null)
					{
						changeSize.sizeChangedEventObject.addEventListener(childSizeChangedHandler);
					}
					this._scrollRectSprite.addChild(this._child);
				}
				childSizeChangedHandler(null);
			}
		}
		
		public function get verticalTrackWidth():Number
		{
			return this._verticalTrack.width;
		}
		
		public function get horizontalTrackHeight():Number
		{
			return this._horizontalTrack.height;
		}

		protected override function childSizeChangedHandler(event:Event):void
		{
			this.calculateProportions();
		}
		
		private function zeroThumbPositions():void
		{
			this._horizontalThumb.x = 0;
			this._verticalThumb.y = 0;
		}
		
		private function calculateFromThumbPositions():void
		{
			this._visibleRectangle.x = 0;
			if (_horizontalVisible)
			{
				this._horizontalPercent = (this._horizontalThumb.x / (_availableWidth - this._horizontalThumb.width));
				this._visibleRectangle.x = this._horizontalPercent * (this._child.width - _availableWidth);
			}
			this._visibleRectangle.y = 0;
			if (_verticalVisible)
			{
				this._verticalPercent = (this._verticalThumb.y / (_availableHeight - this._verticalThumb.height));
				this._visibleRectangle.y = this._verticalPercent * (this._child.height - _availableHeight);
			}
			this._scrollRectSprite.scrollRect = this._visibleRectangle;
		}

		private function calculateProportions():void
		{
			if (this._child != null)
			{
				_horizontalVisible = this._child.width > this._desiredWidth;
				_verticalVisible = this._child.height > this._desiredHeight;
				if (_verticalVisible)
				{
					_horizontalVisible = this._child.width > (this._desiredWidth - this._verticalTrack.width);
				}
				if (_horizontalVisible)
				{
					_verticalVisible = this._child.height > (this._desiredHeight - this._horizontalTrack.height);
				}
				
				this._horizontalTrack.visible = this._horizontalThumb.visible = _horizontalVisible;
				this._verticalTrack.visible = this._verticalThumb.visible = _verticalVisible;
				
				_availableWidth = _verticalVisible ? this._desiredWidth - this._verticalTrack.width : this._desiredWidth
				_availableHeight = _horizontalVisible ? this._desiredHeight - this._horizontalTrack.height : this._desiredHeight;
				
				this._visibleRectangle.width = _availableWidth;
				this._visibleRectangle.height = _availableHeight;
				 
				if (_horizontalVisible)
				{
					this._horizontalTrack.y = this._desiredHeight - this._horizontalTrack.height;
					this._horizontalTrack.width = _availableWidth;
					this._horizontalThumb.width = _availableWidth * (_availableWidth / this._child.width);
					this._horizontalThumb.x = Math.round(this._horizontalPercent * (_availableWidth - this._horizontalThumb.width));
					this._horizontalThumb.y = Math.round(this._desiredHeight - this._horizontalThumb.height);
					this._horizontalDraggable.bounds.x = 0;
					this._horizontalDraggable.bounds.y = Math.round(this._horizontalTrack.y);
					this._horizontalDraggable.bounds.width = Math.round(_availableWidth - this._horizontalThumb.width);
					this._horizontalDraggable.bounds.height = 0;
				}
				
				if (_verticalVisible)
				{
					this._verticalTrack.x = this._desiredWidth - this._verticalTrack.width;
					this._verticalTrack.height = _availableHeight;
					this._verticalThumb.height = _availableHeight * (_availableHeight / this._child.height);
					this._verticalThumb.x = Math.round(this._desiredWidth - this._verticalThumb.width);
					this._verticalThumb.y = Math.round(this._verticalPercent * (_availableHeight - this._verticalThumb.height));
					this._verticalDraggable.bounds.x = Math.round(this._verticalTrack.x);
					this._verticalDraggable.bounds.y = 0;
					this._verticalDraggable.bounds.width = 0;
					this._verticalDraggable.bounds.height = Math.round(_availableHeight - this._verticalThumb.height);
				}
				calculateFromThumbPositions();
			}
			else
			{	
				this._horizontalTrack.visible = this._horizontalThumb.visible = _horizontalVisible = false;
				this._verticalTrack.visible = this._verticalThumb.visible = _verticalVisible = false;
			}
		}
		
		private function horizontalMovedHandler(event:Event):void
		{
			this.calculateFromThumbPositions();
		}
		
		private function horizontalDroppedHandler(event:Event):void
		{
			this.calculateFromThumbPositions();
		}
		
		private function verticalMovedHandler(event:Event):void
		{
			this.calculateFromThumbPositions();
		}
		
		private function verticalDroppedHandler(event:Event):void
		{
			this.calculateFromThumbPositions();
		}
	}
}